package com.dreamchaser.familydevice.shiro.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 重写PathMatchingFilter的路径匹配方法pathsMatch()，加入httpMethod支持。
 * 重写过滤链路径匹配规则，增加REST风格post,get.delete,put..支持
 */
@Slf4j
public abstract class RestPathMatchingFilter extends PathMatchingFilter {
    public RestPathMatchingFilter() {
    }

    /**
     * 重写URL匹配  加入httpMethod支持
     * <p>
     * Returns <code>true</code> if the incoming <code>request</code> matches the specified <code>path</code> pattern,
     * <code>false</code> otherwise.
     * <p/>
     * The default implementation acquires the <code>request</code>'s path within the application and determines
     * if that matches:
     * <p/>
     * <code>String requestURI = {@link #getPathWithinApplication(ServletRequest) getPathWithinApplication(request)};<br/>
     * return {@link #pathsMatch(String, String) pathsMatch(path,requestURI)}</code>
     *
     * @param path    the configured url pattern to check the incoming request against.
     * @param request the incoming ServletRequest
     * @return <code>true</code> if the incoming <code>request</code> matches the specified <code>path</code> pattern,
     * <code>false</code> otherwise.
     */
    @Override
    protected boolean pathsMatch(String path, ServletRequest request) {
        /*String requestURI = this.getPathWithinApplication(request);
        // path: url=method eg: http://api/menu==GET  需要解析出path中的url和httpMethod
        String[] strings = path.split("==");
        if (strings.length <= 1) {
            // 只有url
            return this.pathsMatch(strings[0], requestURI);
        } else {
            // 分割出url+method，， 判断method和request的method是否一致
            return StringUtils.equalsIgnoreCase(WebUtils.toHttp(request).getMethod(), strings[1])
                    // 判断url是否match
                    && this.pathsMatch(strings[0], requestURI);
        }*/
        return true;
    }

    protected Subject getSubject(ServletRequest request, ServletResponse response) {
        return SecurityUtils.getSubject();
    }

    protected abstract boolean isAccessAllowed(ServletRequest var1, ServletResponse var2, Object var3) throws Exception;

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return this.onAccessDenied(request, response);
    }

    protected abstract boolean onAccessDenied(ServletRequest var1, ServletResponse var2) throws Exception;

    @Override
    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return this.isAccessAllowed(request, response, mappedValue) || this.onAccessDenied(request, response, mappedValue);
    }

    protected void saveRequest(ServletRequest request) {
        WebUtils.saveRequest(request);
    }


}
